package com.wallj.videolibrary.base;

import android.content.Context;
import android.graphics.SurfaceTexture;
import android.os.Message;
import android.util.Log;
import android.view.Surface;
import com.eyedog.library.handler.ThreadHandler;
import com.wallj.videolibrary.player.GLVideoSurfaceView;
import com.wallj.videolibrary.player.renderer.OesRenderer;
import io.vov.vitamio.MediaPlayer;
import java.io.IOException;

/**
 * created by jw200 at 2019/5/14 14:36
 **/
public class VideoPlayerInstance extends ThreadHandler {

    private final String TAG = "VideoPlayerInstance";
    protected MediaPlayer mMediaPlayer;
    protected boolean mHasPlayerDisplayed = false;
    protected boolean mHasPlayerPrepared = false;
    protected int mVideoWidth, mVideoHeight;
    protected GLVideoSurfaceView mSurfaceView;
    protected int mCurrentVolume = 100;
    protected SurfaceTexture mSurfaceTexture;
    protected MediaPlayer.OnPreparedListener mPreparedListener;
    protected Context mContext;

    static enum Instance {
        INSTANCE;
        VideoPlayerInstance instance;

        Instance() {
            instance = new VideoPlayerInstance();
        }
    }

    private VideoPlayerInstance() {
    }

    public static VideoPlayerInstance getInstance() {
        return Instance.INSTANCE.instance;
    }

    public void startPlay(Context context, String filepath) {
        this.mContext = context;
        Message displayMessage = obtainThreadMessage(BACK_INIT_PLAYER);
        displayMessage.obj = filepath;
        sendThreadMessage(displayMessage);
    }

    private final int BACK_INIT_PLAYER = 0x01;

    private final int BACK_PLAYER_DISPLAY = 0x02;

    @Override
    public void handleThreadMessage(Message message) {
        super.handleThreadMessage(message);
        switch (message.what) {
            case BACK_INIT_PLAYER: {
                Object obj = message.obj;
                if (obj != null) {
                    String filePath = (String) obj;
                    initMediaPlayer(mContext, filePath);
                }
            }
            break;

            case BACK_PLAYER_DISPLAY:
                Object obj = message.obj;
                if (obj != null) {
                    SurfaceTexture surfaceTexture = (SurfaceTexture) obj;
                    if (mMediaPlayer != null && !mHasPlayerDisplayed) {
                        mMediaPlayer.setSurface(new Surface(surfaceTexture));
                        mMediaPlayer.start();
                        mHasPlayerDisplayed = true;
                    }
                }
                break;
        }
    }

    MediaPlayer.OnBufferingUpdateListener bufferingUpdateListener =
        new MediaPlayer.OnBufferingUpdateListener() {
            @Override
            public void onBufferingUpdate(MediaPlayer mp, int percent) {
                getInstance().onBufferingUpdate(mp, percent);
            }
        };

    protected void onBufferingUpdate(MediaPlayer mp, int percent) {
    }

    MediaPlayer.OnCompletionListener completionListener = new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mp) {
            getInstance().onCompletion(mp);
        }
    };

    protected void onCompletion(MediaPlayer mp) {
    }

    MediaPlayer.OnPreparedListener preparedListener = new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            getInstance().onPrepared(mp);
            mHasPlayerPrepared = true;
            SurfaceTexture surfaceTexture = mSurfaceTexture;
            if (surfaceTexture != null && !mHasPlayerDisplayed) {
                Message displayMessage = obtainThreadMessage(BACK_PLAYER_DISPLAY);
                displayMessage.obj = surfaceTexture;
                sendThreadMessage(displayMessage);
            }
        }
    };

    protected void onPrepared(MediaPlayer mp) {
        if (mPreparedListener != null) {
            mPreparedListener.onPrepared(mp);
        }
    }

    public void setPreparedListener(MediaPlayer.OnPreparedListener listener) {
        this.mPreparedListener = listener;
        if (mHasPlayerPrepared && mPreparedListener != null) {
            mPreparedListener.onPrepared(mMediaPlayer);
        }
    }

    MediaPlayer.OnVideoSizeChangedListener sizeChangedListener =
        new MediaPlayer.OnVideoSizeChangedListener() {
            @Override
            public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
                getInstance().onVideoSizeChanged(mp, width, height);
            }
        };

    protected void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
        mVideoWidth = width;
        mVideoHeight = height;
        if (mSurfaceView != null) {
            mSurfaceView.onInputSizeChanged(width, height);
        }
    }

    private MediaPlayer.OnInfoListener mInfoListener = new MediaPlayer.OnInfoListener() {
        @Override
        public boolean onInfo(MediaPlayer mp, int what, int extra) {
            Log.i(TAG, "onInfo: " + what + ";" + extra);
            getInstance().onInfo(mp, what, extra);
            if (mMediaPlayer != null) {
                if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) {
                    mMediaPlayer.pause();
                } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
                    mMediaPlayer.start();
                }
            }
            return true;
        }
    };

    public void onInfo(MediaPlayer mp, int what, int extra) {
    }

    public void onSurfaceViewCreated(final GLVideoSurfaceView surfaceView) {
        mSurfaceView = surfaceView;
        if (surfaceView != null) {
            surfaceView.setTextureListener(new OesRenderer.TextureListener() {
                @Override
                public void onSurfaceTextureCreated(SurfaceTexture surfaceTexture) {
                    mSurfaceTexture = surfaceTexture;
                    if (mSurfaceView != null && mVideoWidth > 0 && mVideoHeight > 0) {
                        mSurfaceView.onInputSizeChanged(mVideoWidth, mVideoHeight);
                    }
                    Message displayMessage = obtainThreadMessage(BACK_PLAYER_DISPLAY);
                    displayMessage.obj = surfaceTexture;
                    sendThreadMessage(displayMessage);
                }
            });
        }
    }

    private void initMediaPlayer(Context context, String filePath) {
        try {
            if (mMediaPlayer != null) {
                mMediaPlayer.releaseDisplay();
                mMediaPlayer.release();
                mMediaPlayer = null;
            }
            mMediaPlayer = new MediaPlayer(context, true);

            mMediaPlayer.setDataSource(filePath);
            SurfaceTexture surfaceTexture = mSurfaceTexture;
            if (surfaceTexture != null) {
                mMediaPlayer.setSurface(new Surface(surfaceTexture));
                mHasPlayerDisplayed = true;
            }
            mMediaPlayer.prepareAsync();
            mMediaPlayer.setOnBufferingUpdateListener(bufferingUpdateListener);
            mMediaPlayer.setOnCompletionListener(completionListener);
            mMediaPlayer.setOnPreparedListener(preparedListener);
            mMediaPlayer.setOnVideoSizeChangedListener(sizeChangedListener);
            mMediaPlayer.setOnInfoListener(mInfoListener);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void onDestroy() {
        if (mMediaPlayer != null) {
            mPreparedListener = null;
            mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
            mHasPlayerDisplayed = false;
            mHasPlayerPrepared = false;
            mCurrentVolume = 100;
            mVideoWidth = 0;
            mVideoHeight = 0;
            mContext = null;
        }
    }

    public MediaPlayer getMediaPlayer() {
        return mMediaPlayer;
    }

    public boolean hasPlayerPrepared() {
        return mHasPlayerPrepared;
    }

    public int getCurrentVolume() {
        return mCurrentVolume;
    }

    public void setCurrentVolume(int volume) {
        if (mMediaPlayer != null) {
            mCurrentVolume = volume;
            if (volume <= 0) {
                volume = 0;
            } else if (volume >= 100) {
                volume = 100;
            }
            mMediaPlayer.setVolume(1.0f * volume / 100, 1.0f * volume / 100);
        }
    }

    public void pause() {
        if (mMediaPlayer != null) {
            mMediaPlayer.pause();
            mHasPlayerDisplayed = false;
        }
    }
}
